package com.qsmx.qingqiuticket.app.util;

import android.annotation.SuppressLint;
import android.content.Context;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.view.View;

import androidx.appcompat.widget.AppCompatTextView;
import androidx.lifecycle.LifecycleOwner;

import com.al.printerlib.device.CallbackListener;
import com.al.printerlib.device.Printer;
import com.al.printerlib.device.PrinterStatus;
import com.qsmx.core.util.StringUtil;
import com.qsmx.core.util.dialog.DialogUtil;
import com.qsmx.core.util.log.AtmosLogger;
import com.qsmx.core.util.storage.AtmosPreference;
import com.qsmx.qingqiuticket.app.R;
import com.qsmx.qingqiuticket.app.entity.PrintInfoEntity;
import com.qsmx.qingqiuticket.app.event.PrintFinishEvent;
import com.qsmx.qingqiuticket.app.fusion.FusionPre;

import org.greenrobot.eventbus.EventBus;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;

public class PrintUtil {
    private static Printer mDevice;

    private static UsbManager manager;
    private static List<UsbDevice> mUsbList;
    private static int printRetryTimes = 0;

    public static void doPrint(Context context, String printType, AppCompatTextView tvErrorInfo, AppCompatTextView tvRetry, PrintInfoEntity mPrintInfoData, LifecycleOwner lifecycleOwner) {
        printRetryTimes = 0;
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(200);
                    if (printType.equals("1")) {
                        String deviceName = checkDeviceName(context, AtmosPreference.getCustomStringPre(FusionPre.PRINT_ONE));
                        connectUsbDevice(context, deviceName, "print", tvErrorInfo, tvRetry, mPrintInfoData, lifecycleOwner);
                    } else if (printType.equals("2")) {
                        String deviceName = checkDeviceName(context, AtmosPreference.getCustomStringPre(FusionPre.PRINT_TWO));
                        connectUsbDevice(context, deviceName, "print", tvErrorInfo, tvRetry, mPrintInfoData, lifecycleOwner);
                    } else if (printType.equals("3")) {
                        String deviceName = checkDeviceName(context, AtmosPreference.getCustomStringPre(FusionPre.PRINT_THREE));
                        connectUsbDevice(context, deviceName, "print", tvErrorInfo, tvRetry, mPrintInfoData, lifecycleOwner);
                    }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }).start();
    }

    private static void connectUsbDevice(Context context, String serialNumber, String type, AppCompatTextView tvErrorInfo, AppCompatTextView tvRetry, PrintInfoEntity mPrintInfoData, LifecycleOwner lifecycleOwner) {
        mDevice = new Printer(context, serialNumber, new CallbackListener() {
            @Override
            public void onConnecting() {
                AtmosLogger.d("连接中...");
            }

            @Override
            public void onSuccess(String name) {
                if (type.equals("print")) {
                    if (mDevice != null) {
                        PrinterStatus test = getPrinterStatus(mDevice, 500);
                        if (test != null && StringUtil.isNotEmpty(serialNumber)) {
                            System.out.println("打印机编号：+" + serialNumber + "\n打印机状态：" + getPrintStatus(test));
                            if (getPrintStatus(test).equals("正常")) {
                                if (printSample(context, mDevice, mPrintInfoData)) {
                                    new Thread(new Runnable() {
                                        @Override
                                        public void run() {
                                            for (int i = 0; i < 5; i++) {
                                                if (getPrintStatus(test).equals("正常")) {
                                                    EventBus.getDefault().post(new PrintFinishEvent(new Bundle()));
                                                    break;
                                                }
                                                try {
                                                    Thread.sleep(1000);
                                                } catch (InterruptedException e) {
                                                    throw new RuntimeException(e);
                                                }
                                                if (i == 4) {
                                                    DialogUtil.showCardErrorDialog(context, "打印机" + getPrintStatus(test) + "，请联系管理员处理", "确认已处理", new View.OnClickListener() {
                                                        @Override
                                                        public void onClick(View v) {
                                                            DialogUtil.dismissErrorDialog();
                                                            EventBus.getDefault().post(new PrintFinishEvent(new Bundle()));
                                                        }
                                                    });
                                                }
                                            }
                                        }
                                    }).start();
                                }
                            } else if (getPrintStatus(test).equals("重新获取")) {
                                if (printRetryTimes < 3) {
                                    printRetryTimes++;
                                    connectUsbDevice(context, serialNumber, "print", tvErrorInfo, tvRetry, mPrintInfoData, lifecycleOwner);
                                } else {
                                    printRetryTimes = 0;
                                    tvErrorInfo.setVisibility(View.VISIBLE);
                                    tvErrorInfo.setText("打印机状态异常，请稍后重试");
                                    tvRetry.setVisibility(View.VISIBLE);
                                }
                            } else if (getPrintStatus(test).equals("正在打印")) {
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        try {
                                            Thread.sleep(1000);
                                            connectUsbDevice(context, serialNumber, "print", tvErrorInfo, tvRetry, mPrintInfoData, lifecycleOwner);
                                        } catch (InterruptedException e) {
                                            throw new RuntimeException(e);
                                        }
                                    }
                                }).start();
                            } else {
                                tvErrorInfo.setVisibility(View.VISIBLE);
                                tvErrorInfo.setText(getPrintStatus(test));
                                tvRetry.setVisibility(View.VISIBLE);
                            }
                        } else {
                            if (printRetryTimes < 3) {
                                printRetryTimes++;
                                connectUsbDevice(context, serialNumber, "print", tvErrorInfo, tvRetry, mPrintInfoData, lifecycleOwner);
                            } else {
                                printRetryTimes = 0;
                                tvErrorInfo.setVisibility(View.VISIBLE);
                                tvErrorInfo.setText("打印机状态异常，请稍后重试");
                                tvRetry.setVisibility(View.VISIBLE);
                            }
                        }

                    } else {
                        DialogUtil.showCardErrorDialog(context, "打印机未连接", "确定");
                    }
                }
            }

            @Override
            public void onReceive(byte[] data) {

            }

            @Override
            public void onFailure() {
                tvErrorInfo.setVisibility(View.VISIBLE);
                tvErrorInfo.setText("连接失败，请稍后重试");
                tvRetry.setVisibility(View.VISIBLE);
            }

            @Override
            public void onDisconnect() {
                AtmosLogger.d("断开连接");
            }
        });
        mDevice.OpenPort();
    }

    @SuppressLint("NotifyDataSetChanged")
    public static String checkDeviceName(Context context, String PrintNo) {
        String deviceName = "";
        mUsbList = new ArrayList<>();
        manager = (UsbManager) context.getApplicationContext().getSystemService(Context.USB_SERVICE);
        HashMap<String, UsbDevice> devices = manager.getDeviceList();
        Iterator<UsbDevice> deviceIterator = devices.values().iterator();
        int count = devices.size();
        AtmosLogger.d("count " + count);
        if (count > 0) {
            while (deviceIterator.hasNext()) {
                UsbDevice device = deviceIterator.next();
                if (checkUsbDevicePidVid(device)) {
                    mUsbList.add(device);
                }
            }
        } else {
            String noDevices = context.getResources().getText(R.string.none_usb_device).toString();
            AtmosLogger.d("noDevices " + noDevices);
        }

        if (mUsbList != null && !mUsbList.isEmpty()) {
            for (UsbDevice device : mUsbList) {
                if (Objects.equals(device.getSerialNumber(), PrintNo)) {
                    deviceName = device.getDeviceName();
                }
            }
        }
        return deviceName;
    }

    private static PrinterStatus getPrinterStatus(Printer device, int timeoutms) {
        PrinterStatus pst = new PrinterStatus();
        int result = device.GetStatus(pst, timeoutms);
        if (result != 0) {
            return null;
        }
        return pst;
    }

    /**
     * 检查USB设备的PID与VID
     *
     * @param dev
     * @return
     */
    private static boolean checkUsbDevicePidVid(UsbDevice dev) {
        int pid = dev.getProductId();
        int vid = dev.getVendorId();
        return (vid == 0x5a5a && pid == 0x8009);
    }

    private static boolean printSample(Context context, Printer device, PrintInfoEntity mPrintInfoData) {
        try {
            device.InitPrinter();

            device.EnablePM();
            device.SetPrnAreaInPM(5 * 8, 160 * 8, 70 * 8, 35 * 8);
            device.SetDirectionInPM(3);
            //Print text
//            device.SetLeftMargin(0);
            device.SetTextMultiple(1, 1);
            device.LineFeed();
            device.SetAbsHoriPrnPos(40);
            device.PrintText(AtmosPreference.getCustomStringPre(FusionPre.PRINT_BRAND_NAME));
            device.LineFeed();
            device.PrintText(AtmosPreference.getCustomStringPre(FusionPre.PRINT_STORE_NAME));
            device.LineFeed();
            device.LineFeed();
            if (mPrintInfoData.getType().equals("3")) {
                device.LineFeed();
                device.LineFeed();
                device.SetAbsHoriPrnPos(30);
                if (StringUtil.isNotEmpty(mPrintInfoData.getPrintWord())) {
                    device.PrintText(mPrintInfoData.getPrintWord());
                } else {
                    device.PrintText(" ");
                }
            } else {
                device.SetAbsHoriPrnPos(50);
                device.SetQrParameter(6, 49);
                device.PrintQrCode(mPrintInfoData.getQrCode());
            }
            device.LineFeed();
            device.LineFeed();
            device.LineFeed();
            device.LineFeed();
            device.LineFeed();
            device.LineFeed();
            if (!mPrintInfoData.getType().equals("3")) {
                if (StringUtil.isNotEmpty(mPrintInfoData.getTicketPrintName())){
                    if (mPrintInfoData.getTicketPrintName().contains("#")) {
                        device.SetAbsHoriPrnPos(50);
                        device.PrintText(mPrintInfoData.getTicketPrintName().split("#")[0]);
                        device.LineFeed();
                        device.SetAbsHoriPrnPos(40);
                        device.PrintText(mPrintInfoData.getTicketPrintName().split("#")[1]);
                    } else {
                        device.SetAbsHoriPrnPos(50);
                        device.PrintText(mPrintInfoData.getTicketPrintName());
                    }
                } else {
                    device.SetAbsHoriPrnPos(50);
                    device.PrintText(" ");
                }
                device.LineFeed();
                device.LineFeed();
                device.LineFeed();
                device.SetAbsHoriPrnPos(30);
                device.PrintText("场次：" + mPrintInfoData.getSessionNo());
                device.LineFeed();
                device.SetAbsHoriPrnPos(30);
                device.PrintText("日期：" + mPrintInfoData.getSessionDate());
                device.LineFeed();
                device.SetAbsHoriPrnPos(30);
                device.PrintText("时间：" + mPrintInfoData.getSessionTime());
            } else {
                device.SetAbsHoriPrnPos(30);
                device.PrintText(mPrintInfoData.getId().split("-")[mPrintInfoData.getId().split("-").length - 1]);
                device.LineFeed();
            }
            device.PrintPage();
            device.CutPaperEx(0);
            device.ResetPrinter();
            device.ClosePort();
            device = null;
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            DialogUtil.showCardErrorDialog(context, "打印失败,打印机初始化异常", "确定");
            return false;
        }
    }

    private static String getPrintStatus(PrinterStatus printStatus) {
        if (printStatus.bPrinterStatePaperEnd) {
            return "纸张不足";
        } else if (printStatus.bPrinterStatePaperNearEnd) {
            return "纸将尽";
        } else if (printStatus.bPrinterStatePlateOpen) {
            return "开盖错误";
        } else if (printStatus.bPrinterStateCutterError) {
            return "切刀错误";
        } else if (printStatus.bPrinterStateHighTmError) {
            return "热敏感问多过高";
        } else if (printStatus.bPrinterStatePaperJam) {
            return "堵纸错误";
        } else if (printStatus.bPrinterStateHighVoltage) {
            return "高压错误";
        } else if (printStatus.bPrinterStateLowVoltage) {
            return "低压错误";
        } else if (printStatus.bPrinterStateBlackMarkError) {
            return "黑标错误";
        } else if (printStatus.bPrinterStatePrinting) {
            return "正在打印";
        } else if (printStatus.bPrinterStateTestPrinting) {
            return "正在打印自检页";
        } else if (printStatus.bPrinterStateRedundantError) {
            return "冗纸错误";
        } else if (printStatus.bPrinterStateRamError) {
            return "RAM错误";
        } else {
            if (printStatus.btPlateOpenAD != 0 && printStatus.btPaperEndAD != 0) {
                return "正常";
            } else {
                return "重新获取";
            }
        }
    }


}
